package UtilLib;

use strict;
use warnings;
use diagnostics;
use Carp;
use DBM::Deep;
use Exporter qw(import);
use Readonly;

our @EXPORT_OK = qw(get_random_password user_is_valid);

Readonly our %DB_FILE => (
    USERS => "$ENV{SKAL_ROOT}/db/users-passwords.dbmdeep",
); 

sub user_is_valid {
    my $user_password_string = shift
        // croak 'No parameter for user and password string';

    my ($user, $password) = split /:/, $user_password_string;
    my $db = DBM::Deep->new(
        file    => $DB_FILE{USERS},
        locking => 1
    );
    return 1 if (exists $db->{$user} && $db->{$user} eq $password);
    return 0;
}

sub get_random_password {
    my $pwlen = shift
        // croak 'No parameter for password length';
    # Password length

    croak 'Cannot use password of that length' if ($pwlen < 8 || $pwlen > 18);

    my $password;
    # Password has $pwlen characters
    Readonly my @SPECS => (
        q{,}, q{.}, q{-}, q{_}, q{?}, q{!},
        q{+}, q{=}, q{%}, q{/}, q{;}, q{|},
        q{~}, q{*}, q{#}, q{$}, q{&}, q{@},
        q{(}, q{)}, q{[}, q{]}, q{<}, q{>},
        q{\\}, q{\{}, q{\}},
    );
    # Special characters
    Readonly my @ALPHL => ('a' .. 'z');
    # Alphabet lower case
    Readonly my @ALPHU => ('A' .. 'Z');
    # Alphabet upper case
    Readonly my @NUMBS => (0 .. 9);
    # Numbers

    foreach (0 .. $pwlen) {
        my $rand = int rand 4;
        $password .= $SPECS[int rand scalar @SPECS]
            if ($rand == 0);
        $password .= $NUMBS[int rand scalar @NUMBS]
            if ($rand == 1);
        $password .= $ALPHL[int rand scalar @ALPHL]
            if ($rand == 2);
        $password .= $ALPHU[int rand scalar @ALPHU]
            if ($rand == 3);
    }

    return $password;
}

1;

